<?php
/**
 * 自动下载保存远程图片到 Gitee 仓库
 * 
 * @package GiteeImageSaver 
 * @author 星野集xingyeji.com
 * @version 1.0.6
 * @link https://www.xingyeji.com/
 * @license MIT
 */

if (!defined('__TYPECHO_ROOT_DIR__')) exit;

// 引入日志类
require_once __DIR__ . '/log.php';
require_once __DIR__ . '/header.php';
class GiteeImageSaver_Plugin implements Typecho_Plugin_Interface
{
    /**
     * 激活插件方法,如果激活失败,直接抛出异常
     * 
     * @access public
     * @return void
     * @throws Typecho_Plugin_Exception
     */
    public static function activate()
    {
        // 下载保存远程图片
        Typecho_Plugin::factory('Widget_Contents_Post_Edit')->write = ['GiteeImageSaver_Plugin', 'saveFile'];
        Typecho_Plugin::factory('Widget_Contents_Page_Edit')->write = ['GiteeImageSaver_Plugin', 'saveFile'];
        
        // 添加编辑器上传图片钩子
        Typecho_Plugin::factory('Widget_Upload')->uploadHandle = ['GiteeImageSaver_Plugin', 'uploadHandle'];
        Typecho_Plugin::factory('Widget_Upload')->modifyHandle = ['GiteeImageSaver_Plugin', 'modifyHandle'];
        Typecho_Plugin::factory('Widget_Upload')->deleteHandle = ['GiteeImageSaver_Plugin', 'deleteHandle'];
        Typecho_Plugin::factory('Widget_Upload')->attachmentHandle = ['GiteeImageSaver_Plugin', 'attachmentHandle'];
        
        // 添加no-referrer meta标签到页面头部
        Typecho_Plugin::factory('Widget_Archive')->header = array('GiteeImageSaver_Plugin', 'addNoReferrerMeta');
        
        // 添加测试页面
        Helper::addPanel(1, 'GiteeImageSaver/test.php', _t('Gitee图片保存测试'), _t('Gitee图片保存测试'), 'administrator');
        Helper::addAction('GiteeImageSaver', 'GiteeImageSaver_Action');
    }

    /**
     * 获取插件配置面板
     * 
     * @access public
     * @param Typecho_Widget_Helper_Form $form 配置面板
     * @return void
     */
    public static function config(Typecho_Widget_Helper_Form $form)
    {
        // Gitee 仓库配置
        $giteeRepo = new Typecho_Widget_Helper_Form_Element_Text(
            'giteeRepo', 
            NULL, 
            '', 
            _t('Gitee 仓库地址'), 
            _t('例如：https://gitee.com/username/repo')
        );
        $form->addInput($giteeRepo->addRule('required', _t('Gitee 仓库地址不能为空')));
        
        // Gitee 访问令牌
        $giteeToken = new Typecho_Widget_Helper_Form_Element_Text(
            'giteeToken', 
            NULL, 
            '', 
            _t('Gitee 私人令牌'), 
            _t('用于访问 Gitee API 的私人令牌')
        );
        $form->addInput($giteeToken->addRule('required', _t('Gitee 私人令牌不能为空')));
        
        // Git 分支
        $giteeBranch = new Typecho_Widget_Helper_Form_Element_Text(
            'giteeBranch', 
            NULL, 
            'master', 
            _t('Git 分支'), 
            _t('存储图片的Git分支，默认为master，可以为不同站点设置不同分支')
        );
        $form->addInput($giteeBranch);
        
        // 图片保存路径
        $imagePath = new Typecho_Widget_Helper_Form_Element_Text(
            'imagePath', 
            NULL, 
            'images', 
            _t('图片保存路径'), 
            _t('仓库中的图片保存路径，例如：images')
        );
        $form->addInput($imagePath);
        
        // 图片 URL 前缀
        $imageUrlPrefix = new Typecho_Widget_Helper_Form_Element_Text(
            'imageUrlPrefix', 
            NULL, 
            '', 
            _t('图片 URL 前缀'), 
            _t('例如：https://gitee.com/username/repo/raw/master/images，注意：如果修改了Git分支，这里的URL前缀也需要相应修改')
        );
        $form->addInput($imageUrlPrefix->addRule('required', _t('图片 URL 前缀不能为空')));
        
        // 是否保留原始文件名
        $keepOriginalFilename = new Typecho_Widget_Helper_Form_Element_Radio(
            'keepOriginalFilename',
            array(
                '0' => _t('否（使用 MD5 哈希值作为文件名）'),
                '1' => _t('是')
            ),
            '0',
            _t('保留原始文件名'),
            _t('选择是否保留原始文件名，或使用 MD5 哈希值作为文件名')
        );
        $form->addInput($keepOriginalFilename);
        
        // 是否按日期保存图片
        $useDateFolder = new Typecho_Widget_Helper_Form_Element_Radio(
            'useDateFolder',
            array(
                '0' => _t('否（所有图片保存在同一文件夹）'),
                '1' => _t('是（按年/月/日目录结构保存）')
            ),
            '1',
            _t('按日期保存图片'),
            _t('选择是否按照年/月/日的目录结构保存图片')
        );
        $form->addInput($useDateFolder);
        
        // 站点标识
        $siteIdentifier = new Typecho_Widget_Helper_Form_Element_Text(
            'siteIdentifier', 
            NULL, 
            '', 
            _t('站点标识（可选）'), 
            _t('为图片添加站点标识前缀，便于区分不同站点的图片，例如：blog-')
        );
        $form->addInput($siteIdentifier);
    }
    
    /**
     * 禁用插件方法,如果禁用失败,直接抛出异常
     * 
     * @static
     * @access public
     * @return void
     * @throws Typecho_Plugin_Exception
     */
    public static function deactivate(){
        // 移除测试页面
        Helper::removePanel(1, 'GiteeImageSaver/test.php');
        Helper::removeAction('GiteeImageSaver');
    }
    
    /**
     * 个人用户的配置面板
     * 
     * @access public
     * @param Typecho_Widget_Helper_Form $form
     * @return void
     */
    public static function personalConfig(Typecho_Widget_Helper_Form $form){}
    
    /**
     * 添加no-referrer meta标签到页面头部
     * 
     * @access public
     * @return void
     */
    public static function addNoReferrerMeta()
    {
        echo '<meta name="referrer" content="no-referrer" />';
    }
    
    /**
     * 获取保存路径和URL前缀
     * 
     * @access private
     * @param object $options 插件配置
     * @return array [保存路径, URL前缀]
     */
    private static function getSavePathAndUrlPrefix($options)
    {
        // 基础路径和URL前缀
        $basePath = rtrim($options->imagePath, '/');
        
        // 获取URL前缀并替换分支名称
        $baseUrlPrefix = rtrim($options->imageUrlPrefix, '/');
        if (!empty($options->giteeBranch) && $options->giteeBranch != 'master') {
            // 替换URL前缀中的分支名称
            $baseUrlPrefix = preg_replace('/\/raw\/[^\/]+\//', '/raw/' . $options->giteeBranch . '/', $baseUrlPrefix);
            GiteeImageSaver_Log::info('使用自定义分支: ' . $options->giteeBranch . ', URL前缀: ' . $baseUrlPrefix);
        }
        
        // 检查是否使用日期文件夹
        if ($options->useDateFolder == '1') {
            // 获取当前日期，用于创建日期文件夹
            $dateFolder = date('Y/m/d');
            GiteeImageSaver_Log::info('使用日期文件夹: ' . $dateFolder);
            
            // 构建完整的保存路径和URL前缀
            $savePath = $basePath . '/' . $dateFolder;
            $urlPrefix = $baseUrlPrefix . '/' . $dateFolder;
        } else {
            // 不使用日期文件夹
            $savePath = $basePath;
            $urlPrefix = $baseUrlPrefix;
        }
        
        return [$savePath, $urlPrefix];
    }
    
    /**
     * 下载保存远程图片
     * 
     * @access public
     * @param array $post 数据结构体
     * @return array
     */
    public static function saveFile($post)
    {
        try {
            // 设置更长的执行时间限制（5分钟）
            @set_time_limit(300);
            
            // 记录请求信息，帮助调试
            $requestUri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : 'unknown';
            $requestMethod = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'unknown';
            GiteeImageSaver_Log::info('处理请求: ' . $requestMethod . ' ' . $requestUri);
            
            // 检查post参数
            if (!is_array($post)) {
                GiteeImageSaver_Log::error('无效的post参数: ' . gettype($post));
                return $post;
            }
            
            // 检查text字段
            if (!isset($post['text'])) {
                GiteeImageSaver_Log::error('post参数中没有text字段');
                return $post;
            }
            
            GiteeImageSaver_Log::info('开始处理文章内容中的远程图片');
            
            // 获取插件配置
            try {
                $options = Helper::options()->plugin('GiteeImageSaver');
                if (empty($options->giteeRepo) || empty($options->giteeToken) || empty($options->imageUrlPrefix)) {
                    GiteeImageSaver_Log::error('插件配置不完整，无法处理远程图片');
                    return $post;
                }
            } catch (Exception $e) {
                GiteeImageSaver_Log::error('获取插件配置时发生异常: ' . $e->getMessage());
                return $post;
            }
            
            $text = $post['text'];
            
            // 检查文本是否为空
            if (empty($text)) {
                GiteeImageSaver_Log::info('文章内容为空，跳过处理');
                return $post;
            }
            
            // 提取图片URL前先检查文本长度，避免处理过大的文本
            $textLength = strlen($text);
            if ($textLength > 1000000) { // 1MB
                GiteeImageSaver_Log::warning('文章内容过大 (' . $textLength . ' 字节)，可能导致处理超时，跳过处理');
                return $post;
            }
            
            // 提取图片URL
            try {
                $urls = self::getImageFromText($text);
                if (!isset($urls) || count($urls) == 0) {
                    GiteeImageSaver_Log::info('未检测到远程图片，跳过处理');
                    return $post;
                }
                GiteeImageSaver_Log::info('检测到 ' . count($urls) . ' 个远程图片');
            } catch (Exception $e) {
                GiteeImageSaver_Log::error('提取图片URL时发生异常: ' . $e->getMessage());
                return $post;
            }
            
            // 获取相对路径
            $domain = isset($_SERVER['HTTP_HOST']) ? trim($_SERVER['HTTP_HOST']) : '';
            
            // 获取保存路径和URL前缀
            try {
                list($savePath, $urlPrefix) = self::getSavePathAndUrlPrefix($options);
            } catch (Exception $e) {
                GiteeImageSaver_Log::error('获取保存路径和URL前缀时发生异常: ' . $e->getMessage());
                return $post;
            }
            
            // 限制处理的图片数量，避免超时
            $maxImages = 5; // 减少到5张图片，降低超时风险
            $processedCount = 0;
            $failedCount = 0;
            
            // 创建一个新的文本副本，避免直接修改原始文本
            $newText = $text;
            
            foreach ($urls as $url) {
                // 限制处理的图片数量
                if ($processedCount >= $maxImages) {
                    GiteeImageSaver_Log::warning('达到最大处理图片数量限制 (' . $maxImages . ')，跳过剩余图片');
                    break;
                }
                
                // 限制失败次数
                if ($failedCount >= 3) {
                    GiteeImageSaver_Log::warning('失败次数过多，跳过剩余图片处理');
                    break;
                }
                
                try {
                    $url = trim($url);
                    // 跳过本地图片和已经在 Gitee 上的图片
                    if (strpos($url, '://') === false || 
                        (strpos($url, $domain) !== false && !empty($domain)) || 
                        strpos($url, $options->imageUrlPrefix) !== false) {
                        GiteeImageSaver_Log::info('跳过处理图片: ' . $url);
                        continue;
                    }
                    
                    GiteeImageSaver_Log::info('处理远程图片: ' . $url);
                    
                    // 获取不带参数的URL（用于生成文件名）
                    $cleanUrl = preg_replace('/@.*$/', '', $url);
                    GiteeImageSaver_Log::info('清理后的URL: ' . $cleanUrl);
                    
                    // 生成文件名
                    if ($options->keepOriginalFilename == '1') {
                        // 获取URL路径部分
                        $path = parse_url($cleanUrl, PHP_URL_PATH);
                        if ($path === false || $path === null) {
                            GiteeImageSaver_Log::warning('无法解析URL路径: ' . $cleanUrl);
                            $filename = time() . '_image.jpg';
                        } else {
                            // 从路径中提取基本文件名
                            $basename = basename($path);
                            
                            $filename = $basename;
                            // 如果文件名为空或没有扩展名，添加默认扩展名
                            if (empty($filename) || strpos($filename, '.') === false) {
                                $filename = time() . '_image.jpg';
                            } else {
                                // 确保文件名唯一
                                $filename = time() . '_' . $filename;
                            }
                        }
                    } else {
                        $hash = md5($cleanUrl);
                        
                        // 从URL中提取扩展名
                        $path = parse_url($cleanUrl, PHP_URL_PATH);
                        if ($path === false || $path === null) {
                            $ext = 'jpg';
                        } else {
                            $basename = basename($path);
                            $ext = pathinfo($basename, PATHINFO_EXTENSION);
                            
                            // 如果无法获取扩展名，使用默认扩展名
                            if (empty($ext)) {
                                $ext = 'jpg';
                            }
                        }
                        
                        $filename = $hash . '.' . $ext;
                    }
                    
                    // 添加站点标识前缀（如果有）
                    if (!empty($options->siteIdentifier)) {
                        $filename = $options->siteIdentifier . $filename;
                        GiteeImageSaver_Log::info('添加站点标识前缀: ' . $options->siteIdentifier);
                    }
                    
                    GiteeImageSaver_Log::info('生成的文件名: ' . $filename);
                    
                    // 临时下载文件
                    $tempFile = tempnam(sys_get_temp_dir(), 'gitee_');
                    GiteeImageSaver_Log::info('临时文件路径: ' . $tempFile);
                    
                    // 设置下载超时
                    $downloadTimeout = 20; // 减少到20秒下载超时
                    $downloadSuccess = false;
                    
                    try {
                        $downloadSuccess = self::downloadFile($url, $tempFile, $downloadTimeout);
                    } catch (Exception $e) {
                        GiteeImageSaver_Log::error('下载图片异常: ' . $e->getMessage());
                        $downloadSuccess = false;
                    }
                    
                    if ($downloadSuccess) {
                        GiteeImageSaver_Log::info('下载成功，准备上传到 Gitee');
                        
                        // 检测图片类型，如果文件名没有扩展名，则添加正确的扩展名
                        if (strpos($filename, '.') === false) {
                            $ext = self::getImageType($tempFile);
                            $filename = $filename . '.' . $ext;
                            GiteeImageSaver_Log::info('添加扩展名后的文件名: ' . $filename);
                        }
                        
                        // 构建完整的保存路径
                        $giteePath = $savePath . '/' . $filename;
                        GiteeImageSaver_Log::info('Gitee保存路径: ' . $giteePath);
                        
                        // 设置上传超时
                        $uploadTimeout = 30; // 减少到30秒上传超时
                        $uploadSuccess = false;
                        
                        try {
                            $uploadSuccess = self::uploadToGitee($tempFile, $giteePath, $options->giteeRepo, $options->giteeToken, $options->giteeBranch, $uploadTimeout);
                        } catch (Exception $e) {
                            GiteeImageSaver_Log::error('上传到Gitee异常: ' . $e->getMessage());
                            $uploadSuccess = false;
                        }
                        
                        if ($uploadSuccess) {
                            // 生成可访问的URL
                            $newUrl = self::getAccessibleGiteeUrl($urlPrefix, $filename);
                            GiteeImageSaver_Log::info('上传成功，新的URL: ' . $newUrl);
                            
                            // 替换文章中的 URL（包括可能带有参数的URL）
                            try {
                                $newText = self::replaceAllUrlVariants($newText, $url, $newUrl);
                                GiteeImageSaver_Log::info('已替换文章中的URL: ' . $url . ' -> ' . $newUrl);
                                
                                // 增加处理计数
                                $processedCount++;
                            } catch (Exception $e) {
                                GiteeImageSaver_Log::error('替换URL时发生异常: ' . $e->getMessage());
                                $failedCount++;
                            }
                        } else {
                            GiteeImageSaver_Log::error('上传到 Gitee 失败');
                            $failedCount++;
                        }
                        // 删除临时文件
                        @unlink($tempFile);
                        GiteeImageSaver_Log::info('已删除临时文件');
                    } else {
                        GiteeImageSaver_Log::error('下载远程图片失败: ' . $url);
                        $failedCount++;
                    }
                } catch (Exception $e) {
                    GiteeImageSaver_Log::error('处理图片时发生异常: ' . $e->getMessage());
                    $failedCount++;
                    // 继续处理下一张图片
                    continue;
                }
            }
            
            // 更新文章内容
            $post['text'] = $newText;
            GiteeImageSaver_Log::info('文章内容处理完成，成功处理 ' . $processedCount . ' 张图片，失败 ' . $failedCount . ' 张');
            return $post;
        } catch (Exception $e) {
            GiteeImageSaver_Log::error('处理文章内容时发生严重异常: ' . $e->getMessage() . "\n" . $e->getTraceAsString());
            // 返回原始文章内容，确保不会阻止文章发布
            return $post;
        }
    }

    /**
     * 从文本中提取图片 URL
     * 
     * @param string $text 文本内容
     * @return array 图片 URL 数组
     */
    static function getImageFromText($text) {
        // 匹配带后缀的图片链接，包括可能带有@参数的URL
        $pattern1 = '!(https?:\/\/[^\s"\'\)]+\.(?:png|jpg|bmp|jpeg|gif|webp))(@[^\s"\'\)]*)?!i';
        preg_match_all($pattern1, $text, $arr1);
        
        // 匹配Markdown格式的图片链接 ![alt](url)
        $pattern2 = '!\!\[.*?\]\((https?:\/\/[^\s\)]+)\)!i';
        preg_match_all($pattern2, $text, $arr2);
        
        // 匹配HTML格式的图片链接 <img src="url" />
        $pattern3 = '!<img[^>]*src=[\'"]([^\'"\s]+)[\'"][^>]*>!i';
        preg_match_all($pattern3, $text, $arr3);
        
        // 记录日志
        GiteeImageSaver_Log::info('正则匹配结果1: ' . json_encode($arr1[0]));
        GiteeImageSaver_Log::info('正则匹配结果2: ' . json_encode($arr2[1]));
        GiteeImageSaver_Log::info('正则匹配结果3: ' . json_encode($arr3[1]));
        
        $result = [];
        
        // 处理带后缀的图片链接
        if (isset($arr1[0]) && count($arr1[0]) > 0) {
            foreach ($arr1[0] as $v) {
                if (!in_array($v, $result)) {
                    $result[] = $v;
                }
            }
        }
        
        // 处理Markdown格式的图片链接
        if (isset($arr2[1]) && count($arr2[1]) > 0) {
            foreach ($arr2[1] as $v) {
                if (!in_array($v, $result)) {
                    $result[] = $v;
                }
            }
        }
        
        // 处理HTML格式的图片链接
        if (isset($arr3[1]) && count($arr3[1]) > 0) {
            foreach ($arr3[1] as $v) {
                if (!in_array($v, $result)) {
                    $result[] = $v;
                }
            }
        }
        
        GiteeImageSaver_Log::info('提取到的图片URL: ' . json_encode($result));
        return $result;
    }

    /**
     * 替换文本中的所有URL变体，包括带参数的URL
     * 
     * @param string $content 原始内容
     * @param string $src 原始 URL
     * @param string $dst 新 URL
     * @return string 替换后的内容
     */
    static function replaceAllUrlVariants($content, $src, $dst) {
        // 获取不带参数的URL基础部分
        $baseUrl = preg_replace('/@.*$/', '', $src);
        GiteeImageSaver_Log::info('URL基础部分: ' . $baseUrl);
        
        // 1. 直接替换完整URL（包括参数）
        $content = str_ireplace($src, $dst, $content);
        
        // 2. 如果原始URL包含参数，还需要处理可能的变体
        if (strpos($src, '@') !== false) {
            // 查找所有可能的变体（URL基础部分相同但参数可能不同）
            $pattern = '!' . preg_quote($baseUrl, '!') . '@[^\s"\'\)]+!i';
            preg_match_all($pattern, $content, $matches);
            
            if (!empty($matches[0])) {
                foreach ($matches[0] as $match) {
                    if (strcasecmp($match, $src) !== 0) { // 不替换已经替换过的原始URL
                        // 替换这个变体
                        $content = str_ireplace($match, $dst, $content);
                        GiteeImageSaver_Log::info('替换URL变体: ' . $match . ' -> ' . $dst);
                    }
                }
            }
        }
        
        // 3. 处理Markdown格式 ![alt](url)
        $pattern = '!\!\[(.*?)\]\(' . preg_quote($baseUrl, '!') . '(@[^\)]*)?(\))!i';
        $replacement = '![$1](' . $dst . '$3';
        $content = preg_replace($pattern, $replacement, $content);
        
        // 4. 处理HTML格式 <img src="url" />
        $pattern = '!<img([^>]*)src=[\'"]' . preg_quote($baseUrl, '!') . '(@[^\'">]*)?[\'"]([^>]*)>!i';
        $replacement = '<img$1src="' . $dst . '"$3>';
        $content = preg_replace($pattern, $replacement, $content);
        
        return $content;
    }

    /**
     * 替换文本中的 URL（旧方法，保留兼容性）
     * 
     * @param string $content 原始内容
     * @param string $src 原始 URL
     * @param string $dst 新 URL
     * @return string 替换后的内容
     */
    static function replace($content, $src, $dst) {
        return self::replaceAllUrlVariants($content, $src, $dst);
    }

    /**
     * 下载远程文件
     * 
     * @param string $url 远程文件 URL
     * @param string $localPath 本地保存路径
     * @param int $timeout 超时时间（秒）
     * @return boolean 是否下载成功
     */
    static function downloadFile($url, $localPath, $timeout = 30) {
        GiteeImageSaver_Log::info("开始下载远程文件: {$url}");
        
        try {
            // 检查URL是否有效
            if (empty($url) || !filter_var($url, FILTER_VALIDATE_URL)) {
                GiteeImageSaver_Log::error("无效的URL: {$url}");
                return false;
            }
            
            $ch = curl_init($url);
            $fp = @fopen($localPath, 'wb');
            
            if ($fp === false) {
                GiteeImageSaver_Log::error("无法创建本地文件: {$localPath}");
                return false;
            }
            
            // 设置cURL选项
            curl_setopt($ch, CURLOPT_FILE, $fp);
            curl_setopt($ch, CURLOPT_HEADER, 0);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
            curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36');
            curl_setopt($ch, CURLOPT_FAILONERROR, true);
            
            // 添加重试逻辑
            $maxRetries = 2;
            $retryCount = 0;
            $success = false;
            
            while ($retryCount <= $maxRetries && !$success) {
                if ($retryCount > 0) {
                    GiteeImageSaver_Log::info("尝试第 {$retryCount} 次重试下载");
                    // 重置文件指针
                    ftruncate($fp, 0);
                    rewind($fp);
                }
                
                $result = curl_exec($ch);
                $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                $error = curl_error($ch);
                
                if ($result !== false && $httpCode >= 200 && $httpCode < 300) {
                    $success = true;
                } else {
                    $retryCount++;
                    if ($retryCount <= $maxRetries) {
                        // 等待一秒后重试
                        sleep(1);
                    }
                }
            }
            
            curl_close($ch);
            fclose($fp);
            
            if (!$success) {
                GiteeImageSaver_Log::error("下载失败，HTTP代码: {$httpCode}，错误: {$error}");
                @unlink($localPath); // 删除可能部分下载的文件
                return false;
            }
            
            // 验证文件大小
            $fileSize = filesize($localPath);
            if ($fileSize <= 0) {
                GiteeImageSaver_Log::error("下载的文件大小为0，下载失败");
                @unlink($localPath);
                return false;
            }
            
            GiteeImageSaver_Log::info("下载成功，文件大小: {$fileSize} 字节");
            return true;
        } catch (Exception $e) {
            GiteeImageSaver_Log::error("下载过程中发生异常: " . $e->getMessage());
            if (isset($fp) && is_resource($fp)) {
                fclose($fp);
            }
            @unlink($localPath); // 删除可能部分下载的文件
            return false;
        }
    }

    /**
     * 上传文件到 Gitee
     * 
     * @param string $localPath 本地文件路径
     * @param string $remotePath Gitee 中的路径
     * @param string $repo Gitee 仓库地址
     * @param string $token Gitee 私人令牌
     * @param string $branch Git分支名称
     * @param int $timeout 超时时间（秒）
     * @return boolean 是否上传成功
     */
    static function uploadToGitee($localPath, $remotePath, $repo, $token, $branch = 'master', $timeout = 60) {
        try {
            // 检查参数
            if (empty($repo) || empty($token)) {
                GiteeImageSaver_Log::error("仓库地址或令牌为空");
                return false;
            }
            
            // 从仓库地址中提取用户名和仓库名
            $repoPath = parse_url($repo, PHP_URL_PATH);
            if (empty($repoPath)) {
                GiteeImageSaver_Log::error("无法从仓库地址中提取路径: {$repo}");
                return false;
            }
            
            $repoPath = trim($repoPath, '/');
            $repoParts = explode('/', $repoPath);
            
            if (count($repoParts) < 2) {
                GiteeImageSaver_Log::error("仓库地址格式不正确: {$repo}");
                return false;
            }
            
            $owner = $repoParts[0];
            $repoName = $repoParts[1];
            
            // 使用指定的分支，默认为master
            $branch = !empty($branch) ? $branch : 'master';
            GiteeImageSaver_Log::info("准备上传文件到 {$owner}/{$repoName} 仓库的 {$branch} 分支");
            
            // 检查文件是否存在
            if (!file_exists($localPath)) {
                GiteeImageSaver_Log::error("本地文件不存在: {$localPath}");
                return false;
            }
            
            // 读取文件内容并进行 base64 编码
            $content = @file_get_contents($localPath);
            if ($content === false) {
                GiteeImageSaver_Log::error("无法读取本地文件: {$localPath}");
                return false;
            }
            
            $contentBase64 = base64_encode($content);
            $fileSize = strlen($content);
            GiteeImageSaver_Log::info("文件大小: {$fileSize} 字节");
            
            // 检查文件大小是否超过Gitee API限制（通常为30MB）
            $maxSize = 30 * 1024 * 1024; // 30MB
            if ($fileSize > $maxSize) {
                GiteeImageSaver_Log::error("文件大小超过Gitee API限制: {$fileSize} 字节 > {$maxSize} 字节");
                return false;
            }
            
            // 构建 API URL
            $apiUrl = "https://gitee.com/api/v5/repos/{$owner}/{$repoName}/contents/{$remotePath}";
            GiteeImageSaver_Log::info("API URL: {$apiUrl}");
            
            // 构建请求数据
            $data = array(
                'access_token' => $token,
                'content' => $contentBase64,
                'message' => 'Upload image via GiteeImageSaver plugin',
                'branch' => $branch
            );
            
            // 添加重试逻辑
            $maxRetries = 2;
            $retryCount = 0;
            $success = false;
            
            while ($retryCount <= $maxRetries && !$success) {
                if ($retryCount > 0) {
                    GiteeImageSaver_Log::info("尝试第 {$retryCount} 次重试上传");
                    // 等待一秒后重试
                    sleep(1);
                }
                
                // 发送 POST 请求
                $ch = curl_init($apiUrl);
                curl_setopt($ch, CURLOPT_POST, 1);
                curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
                curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
                curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
                curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
                curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
                
                $result = curl_exec($ch);
                $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                $curlError = curl_error($ch);
                curl_close($ch);
                
                if ($httpCode >= 200 && $httpCode < 300) {
                    $success = true;
                } else {
                    $retryCount++;
                    GiteeImageSaver_Log::warning("上传尝试失败，HTTP代码: {$httpCode}，错误: {$curlError}");
                    
                    // 检查是否是因为文件已存在导致的错误
                    if ($httpCode == 422 && strpos($result, 'already exists') !== false) {
                        GiteeImageSaver_Log::info("文件已存在，视为上传成功");
                        $success = true;
                        break;
                    }
                    
                    // 检查是否是因为令牌无效导致的错误
                    if ($httpCode == 401) {
                        GiteeImageSaver_Log::error("令牌无效，放弃重试");
                        break;
                    }
                }
            }
            
            if ($success) {
                GiteeImageSaver_Log::info("上传成功，HTTP代码: {$httpCode}");
                return true;
            } else {
                GiteeImageSaver_Log::error("上传失败，HTTP代码: {$httpCode}，错误: {$curlError}");
                GiteeImageSaver_Log::error("响应内容: {$result}");
                return false;
            }
        } catch (Exception $e) {
            GiteeImageSaver_Log::error("上传过程中发生异常: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * 上传文件处理函数
     * 
     * @access public
     * @param array $file 上传的文件
     * @return mixed
     */
    public static function uploadHandle($file)
    {
        // 记录开始上传
        GiteeImageSaver_Log::info('开始处理上传文件: ' . $file['name']);
        
        // 获取插件配置
        $options = Helper::options()->plugin('GiteeImageSaver');
        if (empty($options->giteeRepo) || empty($options->giteeToken) || empty($options->imageUrlPrefix)) {
            GiteeImageSaver_Log::error('插件配置不完整，无法上传');
            return $file;
        }
        
        // 判断是否为图片文件
        if (0 === strpos($file['type'], 'image/')) {
            GiteeImageSaver_Log::info('检测到图片文件: ' . $file['type']);
            
            // 获取保存路径和URL前缀
            list($savePath, $urlPrefix) = self::getSavePathAndUrlPrefix($options);
            
            // 生成文件名
            if ($options->keepOriginalFilename == '1') {
                // 移除可能的参数（如 @h_1280）
                $cleanName = preg_replace('/@.*$/', '', $file['name']);
                $filename = $cleanName;
                // 确保文件名唯一
                $filename = time() . '_' . $filename;
            } else {
                $hash = md5(file_get_contents($file['tmp_name']));
                // 移除可能的参数（如 @h_1280）
                $cleanName = preg_replace('/@.*$/', '', $file['name']);
                $ext = pathinfo($cleanName, PATHINFO_EXTENSION);
                if (empty($ext)) {
                    $ext = 'jpg';
                }
                $filename = $hash . '.' . $ext;
            }
            
            // 添加站点标识前缀（如果有）
            if (!empty($options->siteIdentifier)) {
                $filename = $options->siteIdentifier . $filename;
                GiteeImageSaver_Log::info('添加站点标识前缀: ' . $options->siteIdentifier);
            }
            
            GiteeImageSaver_Log::info('生成的文件名: ' . $filename);
            
            // 构建完整的保存路径
            $remotePath = $savePath . '/' . $filename;
            GiteeImageSaver_Log::info('准备上传到 Gitee 路径: ' . $remotePath);
            
            if (self::uploadToGitee($file['tmp_name'], $remotePath, $options->giteeRepo, $options->giteeToken, $options->giteeBranch)) {
                // 生成可访问的URL
                $url = self::getAccessibleGiteeUrl($urlPrefix, $filename);
                GiteeImageSaver_Log::info('上传成功，新的URL: ' . $url);
                
                // 返回结果
                return array(
                    'name' => $file['name'],
                    'path' => $url,
                    'size' => $file['size'],
                    'type' => $file['type'],
                    'mime' => $file['type']
                );
            } else {
                GiteeImageSaver_Log::error('上传到 Gitee 失败');
            }
        } else {
            GiteeImageSaver_Log::info('非图片文件，跳过处理: ' . $file['type']);
        }
        
        return $file;
    }
    
    /**
     * 修改文件处理函数
     * 
     * @access public
     * @param array $content 文件内容
     * @param array $file 上传的文件
     * @return mixed
     */
    public static function modifyHandle($content, $file)
    {
        return $content;
    }
    
    /**
     * 删除文件处理函数
     * 
     * @access public
     * @param array $content 文件内容
     * @return mixed
     */
    public static function deleteHandle($content)
    {
        return $content;
    }
    
    /**
     * 获取实际文件绝对访问路径
     * 
     * @access public
     * @param array $content 文件内容
     * @return string
     */
    public static function attachmentHandle($content)
    {
        // 确保返回值始终为字符串
        if (isset($content['path']) && is_string($content['path'])) {
            return $content['path'];
        }
        
        // 如果path不存在或不是字符串，返回一个空字符串
        GiteeImageSaver_Log::warning('attachmentHandle: 无效的路径，返回空字符串');
        return '';
    }
    
    /**
     * 获取图片的实际类型
     * 
     * @param string $filePath 图片文件路径
     * @return string 图片类型（扩展名）
     */
    static function getImageType($filePath) {
        if (!file_exists($filePath)) {
            return 'jpg'; // 默认返回jpg
        }
        
        $info = getimagesize($filePath);
        if ($info === false) {
            return 'jpg'; // 如果无法获取图片信息，默认返回jpg
        }
        
        $mime = $info['mime'];
        switch ($mime) {
            case 'image/jpeg':
                return 'jpg';
            case 'image/png':
                return 'png';
            case 'image/gif':
                return 'gif';
            case 'image/bmp':
                return 'bmp';
            case 'image/webp':
                return 'webp';
            default:
                return 'jpg'; // 默认返回jpg
        }
    }
    
    /**
     * 检查URL是否可访问
     * 
     * @param string $url 要检查的URL
     * @param int $timeout 超时时间（秒）
     * @return boolean 是否可访问
     */
    static function isUrlAccessible($url, $timeout = 3) {
        try {
            if (empty($url)) {
                return false;
            }
            
            $ch = curl_init($url);
            curl_setopt($ch, CURLOPT_NOBODY, true);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
            curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36');
            
            curl_exec($ch);
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            curl_close($ch);
            
            return $httpCode >= 200 && $httpCode < 300;
        } catch (Exception $e) {
            GiteeImageSaver_Log::error("检查URL可访问性时发生异常: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * 获取可访问的Gitee图片URL
     * 
     * @param string $baseUrl 基础URL
     * @param string $filename 文件名
     * @return string 可访问的URL
     */
    static function getAccessibleGiteeUrl($baseUrl, $filename) {
        try {
            // 构建基本URL
            $baseUrlTrimmed = rtrim($baseUrl, '/');
            $originalUrl = $baseUrlTrimmed . '/' . $filename;
            
            // 如果URL中包含分支信息，提取出来用于构建其他格式
            $branch = 'master';
            if (preg_match('/\/raw\/([^\/]+)\//', $baseUrlTrimmed, $matches)) {
                $branch = $matches[1];
                GiteeImageSaver_Log::info('从URL中提取的分支: ' . $branch);
            }
            
            // 尝试不同的URL格式
            $urlFormats = [
                $originalUrl, // 原始格式
                str_replace('/raw/' . $branch . '/', '/raw/' . $branch . '-cdn/', $originalUrl), // CDN格式
            ];
            
            // 如果分支是master，还可以尝试main分支
            if ($branch === 'master') {
                $urlFormats[] = str_replace('/raw/master/', '/raw/main/', $originalUrl);
                $urlFormats[] = str_replace('/raw/master/', '/raw/main-cdn/', $originalUrl);
            }
            
            GiteeImageSaver_Log::info('尝试的URL格式: ' . json_encode($urlFormats));
            
            // 首先快速检查原始URL，大多数情况下这就是正确的
            if (self::isUrlAccessible($originalUrl, 2)) {
                GiteeImageSaver_Log::info('原始URL可访问: ' . $originalUrl);
                return $originalUrl;
            }
            
            // 如果原始URL不可访问，尝试其他格式
            foreach ($urlFormats as $index => $url) {
                if ($index === 0) continue; // 跳过已经检查过的原始URL
                
                if (self::isUrlAccessible($url, 2)) {
                    GiteeImageSaver_Log::info('找到可访问的URL: ' . $url);
                    return $url;
                }
            }
            
            // 如果所有格式都不可访问，返回原始格式
            // 注意：在实际使用中，图片可能需要一些时间才能在Gitee上生效
            GiteeImageSaver_Log::warning('所有URL格式都不可访问，使用原始格式: ' . $originalUrl);
            return $originalUrl;
        } catch (Exception $e) {
            GiteeImageSaver_Log::error("获取可访问URL时发生异常: " . $e->getMessage());
            // 出现异常时返回原始格式
            return rtrim($baseUrl, '/') . '/' . $filename;
        }
    }
}
